package cn.edu.zxj.springblog.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParserBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * Description：jwt 生成 token, 并检验 token 中的内容
 *
 * @author: zxj
 * @date: 2024-02-04
 * @time: 22:58:08
 */
@Slf4j
public class JWTUtils {
    // 过期时间, 单位是 ms, 设置为 30 分钟
    private static final Long Expiration = 30*60*1000L;

    // 密钥, 可以调用下面 genKey 生成, 并复制粘贴
    private static final String secretString = "M6v2NVNUWsHCXB20foSSCquBYMrleVuCbXqVW5fWIgM=";

    // 生成安全密钥
    private static final SecretKey KEY = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));

    /**
     * @description: 生成令牌
     **/
    public static String genJWT(Map<String,Object> claim) {
        String token = Jwts.builder()
                .setClaims(claim) // 自定义内容(负载)
                .setIssuedAt(new Date()) // 设置签名时间
                .setExpiration(new Date(System.currentTimeMillis() + Expiration)) // 设置过期时间
                .signWith(KEY) // 签名算法
                .compact();
        return token;
    }

    /**
     * @description: 验证 token 的合法性, 解析 token
     **/
    public static Claims parseJWT(String token) {
        if (token == null) {
            return null;
        }

        // 创建解析器, 设置签名密钥
        JwtParserBuilder jwtParserBuilder = Jwts.parserBuilder().setSigningKey(KEY);
        Claims claims = null;
        try {
            // 解析token
            claims = jwtParserBuilder.build().parseClaimsJws(token).getBody();
        } catch (Exception e) {
            // 签名认证失败
            log.error("解析令牌失败, token: {}", token);
        }
        return claims;
    }


    /**
     * @description: 生成密钥
     **/
    private static void genKey() {
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        String secretStr= Encoders.BASE64.encode(key.getEncoded());
        // 利用上述得到安全复杂的 secretString
        System.out.println(secretStr);
    }

    /**
     * @description: 从 token 中获取 id
     **/
    public static Integer getUserIdFromToken(String jwtToken) {
        Claims claims = parseJWT(jwtToken);
        if (claims != null) {
            Map<String,Object> map = new HashMap<>(claims);
            return (Integer) map.get("id");
        }

        return null;
    }

}
